/**
 * @file functionImport.c
 * @author aquawius (gitee.com/aquawius) (aquawius@qq.com)
 * @brief 改进班级冤种生成器
 * @version 0.1
 * @date 2022-03-17
 *
 * @copyright Copyright (c) 2022
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>

//定义同学人数,用于初始化姓名数组,应该和names中的数组长度相同
#define NAME_STRINGARRAY_LENGTH 33

//开启调试模式
// #define _FUNCTION_DEBUG_

//生成数组开始的号,默认为0
int startNum = 0;
//生成数组结束的号,默认是names数组长度
int endNum = NAME_STRINGARRAY_LENGTH;

//目标人数
int targetNum;

//程序结束标志
char isExit = 'n';

// 这里姓名数组长度写死,最大姓名长度为10
char names[NAME_STRINGARRAY_LENGTH][11] = {
    "于润铭",
    "马宗一",
    "王帅齐",
    "王佳薪",
    "龙文博",
    "田云彰",
    "刘宇涵",
    "刘述隆",
    "李昀朗",
    "连志铎",
    "陈果",
    "范昕辰",
    "罗洋",
    "季晓涵",
    "孟德意",
    "赵士越",
    "姜雨辰",
    "唐煦征",
    "梁轲涵",
    "韩金钱",
    "薛景震",
    "马文瑞",
    "王靖怡",
    "艾芷竹",
    "邢胜男",
    "刘冉",
    "李琳琳",
    "吴明慧",
    "张琪",
    "陈小敏",
    "董静怡",
    "韩铭玉",
    "quzihang"};

/**
 * @brief 内部函数,清空输入缓冲区
 *
 */
static void clearBuffer()
{
    char ch;
    while ((ch = getchar()) != '\n')
    {
        putchar(ch);
    }
#ifdef _FUNCTION_DEBUG_
    printf("clearBuffered!\n");
#endif
}

/**
 * @brief 用于打印菜单和显示主界面,从这个函数获取相应的值
 *
 */
void displayMenu(int *randomArray)
{
#ifdef _FUNCTION_DEBUG_
    printf("displayMenu() start!\n");
#endif

    puts("\tXX班冤种同学生成器 老曲头版\t");

    printf("动动您那尊贵的小手，输入你要随机选择的人数：\n");
    while (scanf("%d", &targetNum) != 1)
    {
        printf("输入有误! 重新输入!\n");
        clearBuffer();
    }
    clearBuffer();
#ifdef _FUNCTION_DEBUG_
    printf("targetNum input Complete!\n");
#endif
    if (targetNum > 0 && targetNum < NAME_STRINGARRAY_LENGTH)
    {
        printf("你输入了%d\n", targetNum);
        printf("中奖人是:\n");
        for (int i = 0; i < targetNum; i++)
        {
            printf("%d: %s \n", i + 1, names[randomArray[i]]);
        }
#ifdef _FUNCTION_DEBUG_
        printf("names print Complete!\n");
#endif
        printf("是否退出(y/n)");
        while (scanf("%c", &isExit) != 1)
        {
#ifdef _FUNCTION_DEBUG_
            printf("isExit input Complete!\n");
#endif
            printf("输入有误! 重新输入!\n");
        }
        clearBuffer();
    }
    else
    {
        printf("输入有误: %d,请输入一个 0-%d 的数\n", endNum, NAME_STRINGARRAY_LENGTH);
    }
}

/**
 * @brief 核心函数,生成一个不重复随机数数组,长度为endInt-startInt, startInt和endInt为生成随机数范围[startInt,endInt], startInt必须比endInt小
 *
 * @param startInt 随机数范围
 * @param endInt 随机数范围
 * @return int* 生成的不重复随机数数组的头指针
 */
int *generateUnreapetableRandomArray(int startInt, int endInt)
{
    int *a = (int *)malloc(sizeof(int) * endInt - startInt);
    int *b = (int *)malloc(sizeof(int) * endInt - startInt);
#ifdef _FUNCTION_DEBUG_
    printf("malloc Arrays success!\n");
#endif

    int i, j, k;
    // 顺序填充一个数组a作为参考数组
    for (i = 0; i < endInt - startInt; i++)
    {
        a[i] = i + startInt;
    }

    for (i = 0; i < endInt - startInt; i++) // 循环次数
    {
        j = rand() % (endInt - startInt - i);       // j是生成的[0-目标(32)]范围的随机数
        b[i] = a[j];                                // 从参考数组中生成的随机数位置取出数,赋值给需要生成的b数组
        for (k = j; k < endInt - startInt - 1; k++) // k从随机生成的j开始,以(endInt - startInt - i)(修改a,成为越来越小的不重复参考数组范围)
            a[k] = a[k + 1];
    }

#ifdef _FUNCTION_DEBUG_
    printf("generate Arrays success!\n");
#endif

#ifdef _FUNCTION_DEBUG_
    printf("a: ");
    for (int m = 0; m < endNum - startNum; m++)
    {
        printf("%d ", *(a + m));
    }
    printf("\n");

    printf("b: ");
    for (int i = 0; i < endNum - startNum; i++)
    {
        printf("%d ", *(b + i));
    }
    printf("\n");
#endif

    return b;
}

int main()
{
#ifdef _FUNCTION_DEBUG_
    printf("main function Started!\n");
#endif
    //初始化 随机种子
    srand((unsigned)time(NULL));
#ifdef _FUNCTION_DEBUG_
    printf("srand() timerseed creating Complete!\n");
#endif

    //生成指定长度的随机数数组
    while (isExit == 'n')
    {
        int *generatedArray;
        generatedArray = generateUnreapetableRandomArray(startNum, endNum);
        displayMenu(generatedArray);
    }
    puts("Bye!\n");

#ifdef _FUNCTION_DEBUG_
    printf("main function toped!\n");
#endif
}